package com.trz.cqrs.core.entity;

import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import com.trz.cqrs.es.event.priority.Priority;
import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;
import com.trz.cqrs.core.enums.EventState;

import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;


import static java.util.Optional.ofNullable;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.substring;
import static org.apache.commons.lang3.exception.ExceptionUtils.getRootCause;
import static org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace;

@Data
@Accessors(chain = true)
@ToString(callSuper = true)
@TableName("cqrs_event")
@KeySequence("seqGenerator")
public class EventEntity implements Serializable {

    /**
     * 实体标识
     */
    @TableId
    private Long id;

    /**
     * 创建时间戳
     */
    private Date createTime;

    /**
     * 最后更新时间戳
     */
    private Date updateTime = Calendar.getInstance().getTime();

    /**
     * 创建者
     */
    private String createUser;

    /**
     * 最后更新者
     */
    private String updateUser;

    /**
     * 事件类型
     */
    private String eventType;

    /**
     * 事件状态
     */
    private EventState eventState = EventState.CREATED;

    /**
     * 优先级
     */
    private Priority priority = Priority.P1;

    /**
     * 事件载体
     */
    private String payload;

    /**
     * 执行次数
     */
    private int count;

    /**
     * 业务类别
     */
    private String category;

    /**
     * 业务标识
     */
    private String identifier;

    /**
     * 异常类型
     */
    private String exception;

    /**
     * 事件信息
     */
    private String message;

    public EventEntity incrementAndGet() {
        ++count;
        return this;
    }

    public void clearError() {
        setException(null);
        setMessage(null);
    }

    public void onError(Throwable cause) {
        ofNullable(cause).ifPresent(c -> {
            setException(c.getClass().getSimpleName());
            shortenMessage(c.getMessage());
            if (isBlank(c.getMessage())) {
                ofNullable(getRootCause(c)).ifPresent(rc -> {
                    setException(rc.getClass().getSimpleName());
                    shortenMessage(getStackTrace(rc));
                });
            }
        });
    }

    public void shortenMessage(String message) {
        setMessage(substring(message, 0, 500));
    }

}
